<template>
  <div class="tinymce-container">
    <textarea :id="id" class="tinymce-textarea" />
  </div>
</template>

<script>
import { $tooltips } from '@/sun-components/SunMsg.js'
import { getToken } from '@/utils/auth'
import load from './dynamicLoadScript'
import store from '@/store'
// why use this cdn, detail see https://github.com/PanJiaChen/tinymce-all-in-one
// const tinymceCDN = 'https://cdn.jsdelivr.net/npm/tinymce-all-in-one@4.9.3/tinymce.min.js'
const tinymceCDN = '/admin/js/tinymce/tinymce.min.js'
import plugins from './plugins'
import toolbar from './toolbar'
export default {
  name: 'Tinymce',
  props: {
    id: {
      type: String,
      default: function() {
        return ''
      }
    },
    value: {
      type: String,
      default: ''
    },
    visibleSync: {
      type: Boolean,
      default: false
    },
    uploadParameters: {
      type: Object,
      default: function() {
        return {}
      }
    }
  },
  data() {
    return {
      hasChange: false,
      fontsize_formats: '12px 14px 16px 18px 24px 36px 48px',
      font_formats: '微软雅黑=Microsoft YaHei;微软正黑体=Microsoft JhengHei;楷体_GB2312=KaiTi_GB2312;仿宋_GB2312=FangSong_GB2312;楷体=KaiTi;仿宋=FangSong;新宋体=NSimSun;宋体=SimSun;黑体=SimHei;标楷体=DFKai-SB;细明体=MingLiU;新细明体=PMingLiU'
    }
  },
  watch: {
    value(val) {
      if (!this.hasChange) { // 不能直接调用this.setContent() 光标问题
        console.log('val', val)
        this.$nextTick(() =>
          window.tinymce.get(this.tinymceId).setContent(val || '')
        )
      }
    },
    visibleSync(value) {
      if (value) this.init()
    }
  },
  mounted() {
    if (this.visibleSync) this.init()
  },
  destroyed() {
    const tinymce = window.tinymce.get(this.id)
    if (tinymce) {
      tinymce.remove()
      console.log(`销毁id为${this.id}的富文本编辑器`, window.tinymce)
    }
  },
  methods: {
    init() {
      // dynamic load tinymce from cdn
      load(tinymceCDN, (err) => {
        if (err) this.$message.error(err.message)
        if (!err) this.initTinymce()
      })
    },
    initTinymce() {
      const _this = this
      let port = ''
      if (store.getters.publicRoute === 'user') {
        if (store.getters.identity === '1') {
          port = '/api/principal/files'
        }
        if (store.getters.identity === '2') {
          port = '/api/teacher/files'
        }
        if (store.getters.identity === '3') {
          port = '/api/expert/files'
        }
      }
      if (store.getters.publicRoute === 'admin') {
        port = '/api/admin/files'
      }
      window.tinymce.init({
        // language: 'zh_CN', // 语言 'en', 'zh_CN', 'es_MX', 'ja'
        language_url: '/admin/js/tinymce/langs/zh_CN.js', // 语言 'en', 'zh_CN', 'es_MX', 'ja'
        selector: `#${this.id}`, // 必须要
        height: 500,
        with: 'auto',
        plugins: plugins,
        toolbar: toolbar,
        fontsize_formats: this.fontsize_formats,
        font_formats: this.font_formats,
        placeholder: '请再次输入内容', // 内容预展示文本
        branding: false, // 设为false时，隐藏编辑器界面右下角的“Powered by Tiny”（官方汉化为：由Tiny驱动）字样。
        /**
         * 图片
         * http://tinymce.ax-z.cn/plugins/image.php
         */
        image_list: [ // 可选图片列表
          // { title: '水天一色', value: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fup.enterdesk.com%2Fedpic_source%2F53%2F0a%2Fda%2F530adad966630fce548cd408237ff200.jpg&refer=http%3A%2F%2Fup.enterdesk.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639982731&t=a0c2e6f5a62e4cf4fe77c9dabcb28012' },
          // { title: '彩虹', value: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.jj20.com%2Fup%2Fallimg%2Ftp05%2F19100120461512E-0-lp.jpg&refer=http%3A%2F%2Fimg.jj20.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1639982731&t=02ae2ccfc9df7f00a814ffc50c2b1a0a' }
        ],
        image_advtab: false, // 高级参数 为图像属性编辑窗口添加高级属性，可以自定义图片的css样式（内置style）、边距（margin）和边框（border）。
        image_description: true, // 显示隐藏图片说明input
        image_dimensions: true, // 显示隐藏图片尺寸input
        image_title: false, // 显示隐藏图片标题input
        paste_data_images: true, // 粘贴data格式的图像
        // image_prepend_url: '', // 指定图片URL补齐前缀
        images_upload_handler: function(blobInfo, success, failure, progress) { // 图片上传
          console.log('blobInfo', blobInfo)
          const file = blobInfo.blob()
          const formData = new FormData()
          try {
            console.log('blobInfo.filename()', blobInfo.filename())
            const xhr = new XMLHttpRequest()
            xhr.open('POST', port, true)
            xhr.setRequestHeader('Authorization', getToken())
            formData.append('name', blobInfo.filename().substring(0, blobInfo.filename().lastIndexOf('.')))
            formData.append('file', file)
            const keysValue = Object.keys(_this.uploadParameters)
            keysValue.forEach(k => {
              formData.append(k, _this.uploadParameters[k])
            })
            xhr.onerror = (error) => {
              console.log('error', error)
            }
            xhr.ontimeout = function timeout() {
              $tooltips('上传超时，请刷新重试...', 'warning')
            }
            xhr.onprogress = (evt) => {
              console.log('evt', evt)
              const imgLoadPercent = Math.round(evt.loaded / evt.total * 100)
              console.log('上传进度')
              progress(imgLoadPercent)
            }
            xhr.send(formData)
            xhr.onreadystatechange = () => {
              if (xhr.readyState === 4 && xhr.status === 201) {
                const response = JSON.parse(xhr.response)
                success(response.data.url)
              }
              if (xhr.status === 404) {
                failure('404：上传接口异常' + port)
              }
            }
          } catch (error) {
            console.log('上传失败', error)
            failure('出现未知问题，请刷新页面重试，或联系管理员')
          }
        },
        /**
         * 超链接
         * http://tinymce.ax-z.cn/plugins/link.php
         */
        link_default_protocol: 'http', // 可通过此参数改变链接默认使用的协议。
        default_link_target: '_blank', // 默认链接打开方式
        link_assume_external_targets: false, // 协议前缀补齐提示
        link_context_toolbar: true, // 链接的右键增强菜单
        link_list: [ // 链接列表
          // { title: 'My page 1', value: 'https://www.tiny.cloud' },
          // { title: 'My page 2', value: 'https://about.tiny.cloud' }
        ],
        link_title: false, // 对话框中“标题”的显示开关
        target_list: [ // 指定打开方式列表
          { title: '当前窗口', value: '' },
          { title: '新窗口', value: '_blank' }
        ],
        /**
         * 视频 媒体
         * http://tinymce.ax-z.cn/plugins/media.php
         */
        media_live_embeds: true, // 默认： true 开启此选项后，用户可看到编辑区内嵌入视频的实时预览，而不是占位图
        media_alt_source: false, // 显示隐藏资源备用地址输入框
        media_poster: true, // 显示隐藏图片封面输入框
        media_dimensions: true, // 显示隐藏宽高尺寸输入框
        video_template_callback: function(data) { // 自定义插入视频代码
          console.log('自定义插入视频代码', data)
          return '<video width="' + data.width + '" height="' + data.height +
            '"' + (data.poster ? ' poster="' + data.poster + '"' : '') +
            ' controls="controls">\n' + '<source src="' + data.source1 + '"' +
            (data.source1mime ? ' type="' + data.source1mime + '"' : '') + ' />\n' +
            (data.source2 ? '<source src="' + data.source2 + '"' +
            (data.source2mime ? ' type="' + data.source2mime + '"' : '') + ' />\n' : '') +
            '</video>'
        },
        media_url_resolver: function(data, resolve, reject) { // 自定义生成逻辑
          console.log('自定义生成逻辑', data)
          if (!data.url) return
          try {
            if (data.url.indexOf('YOUR_SPECIAL_VIDEO_URL') !== -1) {
              const embedHtml = ''
              resolve({ html: embedHtml })
            } else {
              resolve({ html: '' }) // 如果你还想用默认生成逻辑，传一个空字符串给它就好了。
            }
          } catch { // 如果函数中出现错误，而你希望给用户提醒，可以使用reject回调。
            reject({ msg: '自定义插入视频代码信息错误' })
          }
        },
        /**
         * 文件上传回调：配置此选项将在图片、媒体、链接对话框中加入上传文件功能
         * callback：上传成功后执行的回调函数有三个参数：第一个上传结果，第二个object定义了要填入对话框中的字段键值
         * value：当前受影响的字段值
         * meta：为一个包含指定对话框中其它字段值的对象（meta.filetype是当前对话框的文件类型）
         */
        file_picker_callback: function(callback, value, meta) {
          let filetype = ''
          switch (meta.filetype) {
            case 'image':
              filetype = '.jpg, .jpeg, .png, .gif, .pic, .tif, .bmp'
              break
            case 'media':
              filetype = '.mp4, .3gp, .m4v, .rmvb, .avi, .wmv'
              break
            case 'file':
              filetype = '.doc, .docx, .xls, .xlsx, .ppt, .pptx, .pdf'
              break
          }
          var input = document.createElement('input')
          input.setAttribute('type', 'file')
          input.setAttribute('accept', filetype)
          input.click()
          input.onchange = function(e) {
            const file = this.files[0] // 已经是blob类型 注：this作用域
            const formData = new FormData()
            const xhr = new XMLHttpRequest()
            xhr.open('POST', port, true)
            xhr.setRequestHeader('Authorization', getToken())
            formData.append('name', file.name.substring(0, file.name.lastIndexOf('.')))
            formData.append('file', file)
            const keysValue = Object.keys(_this.uploadParameters)
            keysValue.forEach(k => {
              formData.append(k, _this.uploadParameters[k])
            })
            xhr.onerror = (error) => {
              console.log('上传失败', error)
            }
            xhr.ontimeout = function timeout() {
              $tooltips('上传超时，请刷新重试...', 'warning')
            }
            xhr.send(formData)
            xhr.onreadystatechange = () => {
              if (xhr.readyState === 4 && (xhr.status === 201 || xhr.status === 200)) {
                const response = JSON.parse(xhr.response)
                console.log('上传成功------file_picker_callback------', response.data)
                callback(response.data.url, { text: file.name })
              }
            }
          }
        },
        // 实例化结束
        init_instance_callback: editor => {
          console.log('editor', _this.value)
          editor.setContent(_this.value || '')
          editor.on('NodeChange Change KeyUp SetContent', () => { // 必须设置才能监听到value
            _this.hasChange = true
            _this.$emit('input', editor.getContent())
          })
        }
      })
    },
    setContent(value) {
      window.tinymce.get(this.id).setContent(value)
      console.log('id------', this.id, value)
    }
  }
}
</script>

<style lang="scss" scoped>
.tinymce-container {
  position: relative;
  line-height: normal;
}

.tinymce-textarea {
  visibility: hidden;
  z-index: -1;
}

.editor-custom-btn-container {
  position: absolute;
  right: 4px;
  top: 4px;
  /*z-index: 2005;*/
}
.editor-upload-btn {
  display: inline-block;
}
</style>
